# -*- coding: utf-8 -*-
__author__ = 'shijin'

import sys
import inspect
import re
import socket
import json
# from django.contrib.auth.models import User, Group
# from django.db.models import Q

from urllib import request, error
import traceback

import logging
from utils.util_logfile import nlogger, slogger, flogger, traceback


class DoPostError(Exception): pass


class DoGetError(Exception): pass


def get_current_function_name():
    # print(sys._getframe().f_code.co_name) #返回 get_current_function_name 函数名
    # print(inspect.stack()[0][3])  #返回 自身的函数信息
    return inspect.stack()[1][3]  # 返回 调用的上一级方法或函数信息


def get_class_name(class_obj):  # 返回传入的对象实例 的类型名称
    if isinstance(class_obj, (object,)):
        return class_obj.__class__.__name__


def is_port(number):
    try:
        number = int(number)
        if number < 0 or number > 65535: raise ValueError("Port Invalid")
        return isinstance(number, int)
    except Exception:
        return False


def get_port(ports, return_type='str'):
    """ check ports and return str or list"""
    port_list = list()
    try:
        if ports and isinstance(ports, str):
            # port_list = ports.split(',')
            port_list = re.split(',|，|、', ports)
        elif ports and isinstance(ports, list):
            port_list = ports
        else:
            raise ValueError("变量端口数据类型不合法！")

        if port_list:
            port_list = list(set(list(filter(None, port_list))))
            _port_list = list(filter(is_port, port_list))
            if len(port_list) == len(_port_list):
                _port_list.sort(key=int)
                if return_type == 'str':
                    _port_list = [str(i) for i in _port_list]
                    return ','.join(_port_list)
                else:
                    return _port_list
            else:
                raise ValueError("变量端口中包含非法字符！")
        else:
            raise ValueError("变量端口为空值！")
    except ValueError:
        raise
    except Exception:
        nlogger.error("get_port error: {e}".format(e=traceback.format_exc()))
        raise ValueError("获取端口失败！")


def get_hostname():
    """ :return hostname """
    try:
        return socket.gethostname()
    except:
        return None


def get_host_ip(connect_ip, connect_port):
    """ :param connect_ip connect remote host ip
               connect_port connect remote host port
        :return ip or None
    """
    s = None
    ip = None
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        s.connect((connect_ip, connect_port))
        ip = s.getsockname()[0]
    finally:
        if s is not None:
            s.close()
        return ip


def _do_post(url, **kwargs):
    """
        request post method
    """
    DEFAULT_HEADERS = {'Content-type': "application/json;charset=utf-8"}
    kwargs = kwargs if kwargs else {}
    data = bytes(json.dumps(kwargs), encoding='utf-8')
    # 序列化时对中文默认使用的ascii编码.想输出中文需要指定ensure_ascii = False（此时编码为utf - 8）：
    # data = json.dumps(kwargs, ensure_ascii=False)
    req = request.Request(url=url, data=data, headers=DEFAULT_HEADERS, method="POST")

    for i in range(2):
        _timeout = 5 * i + 5
        try:
            res = request.urlopen(req, timeout=_timeout)
            if res:
                result = json.loads(str(res.read(), encoding='utf-8'))
                slogger.info("url: {u}, request.data: {d}, response.status: {s}, response.data: {r}"
                             .format(u=url, d=data, s=res.status, r=result))
                return result
            else:
                continue
        except error.HTTPError as e:
            nlogger.error("post request failed, url: {u}, code: {c}!".format(u=url, c=e.code))
            continue
        except error.URLError as e:
            nlogger.error("post request failed, url: {u}, code: {c}!".format(u=url, c=e.reason))
            continue
        except Exception as e:
            nlogger.error("post request failed, url: {u}, {e} !".format(u=url, e=repr(e)))
            continue
    else:
        raise DoPostError('_do_post error,request failed !')


def _do_get(url, **kwargs):
    """
        request get method
    """

    value = None
    if kwargs:
        value_list = ['{0}={1}'.format(k, v) for k, v in kwargs.items()]
        value = '&'.join(value_list)

    url = url + value if value else url
    req = request.Request(url=url)

    for i in range(3):
        _timeout = 5 * i + 5
        try:
            res = request.urlopen(req, timeout=_timeout)
            if res:
                return json.loads(str(res.read(), encoding='utf-8'))
            else:
                continue
        except error.HTTPError as e:
            nlogger.error("get request failed {0}, {1}!".format(url, e.code))
            continue
        except error.URLError as e:
            nlogger.error("get request failed {0}, {1}!".format(url, e.reason))
            continue
        except Exception as e:
            nlogger.error("get request failed {0}, {1} !".format(url, repr(e)))
            continue
    else:
        raise DoGetError('_do_get error,request failed !')
